#pragma once

#include "Sock.hpp"
#include <vector>
#include <functional>
#include <pthread.h>

namespace ns_tcpserver
{
    using func_t = std::function<void(int)>; // 回调，让tcp完成的方法

    class TcpServer; // 声明一下

    class ThreadData // 线程数据，当结构体使用
    {
    public:
        ThreadData(int sock, TcpServer *server)
            :_sock(sock)
            , _server(server)
        {}
        ~ThreadData() 
        {}
    public:
        int _sock;
        TcpServer *_server;
    };

    class TcpServer
    {
    private:
        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData *td = static_cast<ThreadData *>(args); // 得到线程数据后强转
            td->_server->Excute(td->_sock); // 线程内部调用要执行的方法
            close(td->_sock);
            return nullptr;
        }
    public:
        TcpServer(const uint16_t &port, const std::string &ip = "0.0.0.0") // 构造函数初始化
        {
            _listensock = _sock.Socket();
            _sock.Bind(_listensock, port, ip);  
            _sock.Listen(_listensock);
        }

        void BindService(func_t func)  // 绑定一个服务方法
        { 
            _func.push_back(func);
        }

        void Excute(int sock) // 执行被绑定的方法
        {
            for(auto &f : _func) // 遍历所有方法让线程去执行
            {
                f(sock);
            }
        }

        void Start()
        {
            while(true) // 不断获取新链接
            {
                std::string clientip;
                uint16_t clientport;
                int sock = _sock.Accept(_listensock, &clientip, &clientport);
                if (sock == -1)
                    continue;
                logMessage(NORMAL, "create new link success, sock: %d", sock);
                pthread_t tid; // 多线程式的服务
                ThreadData *td = new ThreadData(sock, this); // 线程处理网络服务，要得到sock
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

        ~TcpServer()
        {
            if (_listensock >= 0)
                close(_listensock);
        }
    private:
        int _listensock;
        Sock _sock;
        std::vector<func_t> _func;
    };
}